﻿using System;
using System.Reflection;
using System.Xml.Linq;

namespace Phoenix.Xna.Framework.Serialization.Markup.Fields
{
    /// <summary>
    /// Base class for all IMarkupField types.
    /// </summary>
    /// <typeparam name="T">The type of the internal IMarkupObject.</typeparam>
    internal abstract class MarkupFieldBase<T> : IMarkupField
    {
        protected T _value;   // The value of the markup object.

        #region IMarkupElement Members

        /// <summary>
        /// Gets or sets the SerializationService that provides context to references, etc.
        /// </summary>
        public Serializer Serializer { get; set; }

        /// <summary>
        /// Serialize the element to XML.
        /// </summary>
        /// <returns>The element markup serialzed as an XElement.</returns>
        public abstract XElement Serialize();

        /// <summary>
        /// Deserialize the element from an XElement.
        /// </summary>
        /// <param name="element">The XElement to deserialize this element from.</param>
        public abstract void Deserialize(XElement element);

        #endregion

        #region IMarkupField Members

        /// <summary>
        /// Gets or sets the property name
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the System.Type of the defined object.
        /// </summary>
        public Type ObjectType { get; set; }

        /// <summary>
        /// Gets a value indicating that this property is not default, and should be serialized.
        /// </summary>
        public bool ShouldPersist { get; protected set; }

        /// <summary>
        /// Extract the markup information from the FieldInfo for this field.
        /// </summary>
        /// <param name="field">The FieldInfo for this field.</param>
        /// <param name="value">The value of the field.</param>
        public abstract void ExtractMarkup(FieldInfo field, object value);

        /// <summary>
        /// Sets the dereferenced value to the instance's field.
        /// </summary>
        /// <param name="instance">The instance to set the field on.</param>
        public abstract void SetValue(object instance);

        #endregion
    }
}
